﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Zgq.WindowsForms
{
    public partial class frmCreateModel : Form
    {
        private string xmlPath = System.AppDomain.CurrentDomain.BaseDirectory + "C5Config.xml";
        public BindingList<SYS_ENTITIES> EntityList = null;
        public int CurFormType = 0;

        public frmCreateModel()
        {
            InitializeComponent();
        }

        private void frmCreateModel_Load(object sender, EventArgs e)
        {
            this.rgSysEntity.DataSource = EntityList;
            this.cmbModul.BindData("SYSMODEL");

            var codeColumn = this.rgSysEntity.Columns["ENTITY_CODE"] as GridViewDataColumn;
            codeColumn.ReadOnly = true;
            var nameColumn = this.rgSysEntity.Columns["ENTITY_NAME"] as GridViewDataColumn;
            nameColumn.ReadOnly = true;

            GetXmlInfo();
            this.rb1.Checked = true;
        }

        /// <summary>
        /// 选择目录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSelFile_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fb = new FolderBrowserDialog();
            if (fb.ShowDialog() == DialogResult.OK)
            {
                this.txtFilePath.Text = fb.SelectedPath;
            }
        }

        /// <summary>
        /// 文件校验
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private bool CheckFile(string filePath)
        {
            string extension = Path.GetExtension(filePath);
            if (extension != ".cs")
            {
                MessageBox.Show("请选择正确的文件");
                return false;
            }
            return true;
        }

        /// <summary>
        /// 生成
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnMultiCreate_Click(object sender, EventArgs e)
        {
            try
            {
                if (EntityList == null || EntityList.Count == 0)
                {
                    MessageBox.Show("数据异常");
                    return;
                }

                if (string.IsNullOrWhiteSpace(this.txtFilePath.Text) || string.IsNullOrWhiteSpace(this.txtNameSpace.Text))
                {
                    MessageBox.Show("请选择正确的文件路径和命名空间");
                    return;
                }

                if (!Directory.Exists(this.txtFilePath.Text.Trim()))
                {
                    MessageBox.Show("文件路径错误");
                    return;
                }

                var list = EntityList.Where(x => x.IsSelected).ToList();
                if (list.Count == 0)
                {
                    MessageBox.Show("没有选择任何数据");
                    return;
                }

                this.btnMultiCreate.Enabled = false;
                SaveXml();
                list.ForEach(x => { CreateModelInfo(x); });
                this.btnMultiCreate.Enabled = true;
                MessageBox.Show("生成成功");
                //清空选中项
                list.ForEach(x => { x.IsSelected = false; });
            }
            catch (Exception ex)
            {
                this.btnMultiCreate.Enabled = true;
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 创建实体
        /// </summary>
        private void CreateModelInfo(SYS_ENTITIES sysEntities)
        {
            string filePath = this.txtFilePath.Text.Trim();
            string realyPath = string.Format(@"{0}\{1}.cs", filePath, sysEntities.ENTITY_CODE.Trim());
            string allTxt = string.Empty;
            if (this.rb1.Checked)
            {
                AddTableModel(ref allTxt, realyPath, sysEntities.ENTITY_CODE.Trim(), null, true);
            }
            else if (this.rb2.Checked)
            {
                var list = SLUtility.CallMethodList("SysEntities", "GetEntityLineList", sysEntities.ENTITY_ID, CurFormType, sysEntities.ENTITY_CODE.Trim()).Cast<SYS_ENTITIES_LINES>().ToList();
                AddTableModel(ref allTxt, realyPath, sysEntities.ENTITY_CODE.Trim(), list.OrderBy(x => x.Seq).ToList(), false);
            }

            WriteModel(realyPath, allTxt);
        }

        /// <summary>
        /// 写文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="allTxt"></param>
        private void WriteModel(string filePath, string allTxt)
        {
            File.WriteAllText(filePath, allTxt);
        }

        /// <summary>
        /// 读取表字段描述等信息
        /// </summary>
        /// <param name="allTxt"></param>
        /// <param name="filePath"></param>
        /// <param name="entityCode"></param>
        /// <param name="sysEntitiesLineList"></param>
        /// <param name="IsDbData"></param>
        private void AddTableModel(ref string allTxt, string filePath, string entityCode)
        {
            string currTableInfo = string.Empty;
            StringBuilder modelClassStringBuilder = new StringBuilder();
            //引用
            modelClassStringBuilder.AppendLine("using System;");
            modelClassStringBuilder.AppendLine("using System.Runtime.Serialization;");
            modelClassStringBuilder.AppendLine("using C5CommonTools;");
            modelClassStringBuilder.AppendLine("using WCFModule;");
            modelClassStringBuilder.AppendLine("");

            //命名空间
            modelClassStringBuilder.AppendLine(string.Format("namespace {0}", this.txtNameSpace.Text.Trim()));
            modelClassStringBuilder.AppendLine("{");

            List<DBTableColmnsInfo> TColumnsList = null;
            if (IsDbData)
            {
                var list = SLUtility.CallMethodList("SysEntities", "GetTableColumnInfo", entityCode);
                TColumnsList = list.Cast<DBTableColmnsInfo>().ToList();
            }

            //对象特性
            string modelAttr = GetTableAttributes(IsDbData, sysEntitiesLineList, TColumnsList);
            if (!string.IsNullOrWhiteSpace(modelAttr))
                modelClassStringBuilder.AppendLine(string.Format("    {0}", modelAttr));

            //表
            currTableInfo = string.Format("public partial class {0} : {1}", entityCode, this.txtBaseModel.Text.Trim());
            modelClassStringBuilder.AppendLine(string.Format("    {0}", currTableInfo));
            modelClassStringBuilder.AppendLine("    {");

            //字段
            modelClassStringBuilder.AppendLine(GetColumnStr(TColumnsList));

            //表
            modelClassStringBuilder.AppendLine("    }");

            //命名空间
            modelClassStringBuilder.AppendLine("}");

            allTxt = modelClassStringBuilder.ToString();
        }

        /// <summary>
        /// 获取字段信息
        /// </summary>
        /// <param name="listTColumn"></param>
        /// <returns></returns>
        private string GetColumnStr(List<DBTableColmnsInfo> listTColumn = null)
        {
            StringBuilder modelClassStringBuilder = new StringBuilder();

            if (IsDbData)
            {
                #region 数据库

                //循环写入列信息
                if (listTColumn != null && listTColumn.Count > 0)
                {
                    listTColumn.ForEach(y =>
                    {
                        //获取描述信息
                        string currColumnDescription = y.ReMark;

                        bool canNull = false;
                        if (!y.PrimaryKey && !y.AutoIncrement && y.IsNullable == 1)
                            canNull = true;

                        string currType = GetDataType(-1, y.DbType, canNull, 1, IsDbData);

                        //私有字段
                        modelClassStringBuilder.AppendLine(string.Format("        private {0} _{1};", currType, y.FieldName.Trim()));

                        //描述
                        modelClassStringBuilder.AppendLine("        /// <summary>");
                        modelClassStringBuilder.AppendLine(string.Format("        /// {0}", currColumnDescription));
                        modelClassStringBuilder.AppendLine("        /// </summary>");

                        //特性
                        modelClassStringBuilder.AppendLine(string.Format("        {0}", GetAttributes(y.AutoIncrement, y.PrimaryKey, y.DbType, y.MaxLength, y.Scale, y.Precision)));
                        //特性
                        modelClassStringBuilder.AppendLine("        [DataMember]");

                        //访问器
                        modelClassStringBuilder.AppendLine(string.Format("        public {0} {1}", currType, y.FieldName.Trim()));
                        modelClassStringBuilder.AppendLine("        {");
                        modelClassStringBuilder.AppendLine("            get");
                        modelClassStringBuilder.AppendLine("            {");
                        modelClassStringBuilder.AppendLine(string.Format("                return _{0};", y.FieldName.Trim()));
                        modelClassStringBuilder.AppendLine("            }");
                        modelClassStringBuilder.AppendLine("            set");
                        modelClassStringBuilder.AppendLine("            {");
                        modelClassStringBuilder.AppendLine(string.Format("                _{0} = value;", y.FieldName.Trim()));
                        modelClassStringBuilder.AppendLine(string.Format("                RaisePropertyChanged(\"{0}\");", y.FieldName.Trim()));
                        modelClassStringBuilder.AppendLine("            }");
                        modelClassStringBuilder.AppendLine("        }");
                    });
                }

                #endregion
            }
            else
            {
                #region 实体表

                //循环写入列信息
                if (listEntity != null && listEntity.Count > 0)
                {
                    listEntity.ForEach(y =>
                    {
                        //获取描述信息
                        string currColumnDescription = y.DefaultCaption;

                        bool canNull = false;
                        if ((y.IsKey == false || y.IsKey == null) && (y.IsIdentity == false || y.IsIdentity == null))
                            canNull = true;

                        string currType = GetDataType(y.FIELD_TYPE.ToInt(), "", canNull, 1, IsDbData);

                        //私有字段
                        modelClassStringBuilder.AppendLine(string.Format("        private {0} _{1};", currType, y.FIELD_CODE.Trim()));

                        //描述
                        modelClassStringBuilder.AppendLine("        /// <summary>");
                        modelClassStringBuilder.AppendLine(string.Format("        /// {0}", currColumnDescription));
                        modelClassStringBuilder.AppendLine("        /// </summary>");

                        //特性
                        modelClassStringBuilder.AppendLine(string.Format("        {0}", GetAttributes(y.IsIdentity ?? false, y.IsKey ?? false, GetDataType(y.FIELD_TYPE.ToInt(), "", canNull, 2, IsDbData), y.FIELD_LENGTH ?? 1, 0, 0)));
                        //特性
                        modelClassStringBuilder.AppendLine("        [DataMember]");

                        //访问器
                        modelClassStringBuilder.AppendLine(string.Format("        public {0} {1}", currType, y.FIELD_CODE.Trim()));
                        modelClassStringBuilder.AppendLine("        {");
                        modelClassStringBuilder.AppendLine("            get");
                        modelClassStringBuilder.AppendLine("            {");
                        modelClassStringBuilder.AppendLine(string.Format("                return _{0};", y.FIELD_CODE.Trim()));
                        modelClassStringBuilder.AppendLine("            }");
                        modelClassStringBuilder.AppendLine("            set");
                        modelClassStringBuilder.AppendLine("            {");
                        modelClassStringBuilder.AppendLine(string.Format("                _{0} = value;", y.FIELD_CODE.Trim()));
                        modelClassStringBuilder.AppendLine(string.Format("                RaisePropertyChanged(\"{0}\");", y.FIELD_CODE.Trim()));
                        modelClassStringBuilder.AppendLine("            }");
                        modelClassStringBuilder.AppendLine("        }");

                    });
                }

                #endregion
            }

            return modelClassStringBuilder.ToString();
        }


        private string[] NotCanNull = new string[] { "string", "byte[]" };

        /// <summary>
        /// 获取C#和Sql Server数据类型
        /// </summary>
        /// <param name="dataType"></param>
        /// <param name="canNull"></param>
        /// <param name="type">1:C#类型 2:Sql类型 </param>
        /// <returns></returns>
        private string GetDataType(int dataType, string dbType, bool canNull, int type, bool IsDbData)
        {
            string result = null;
            DataType dType = null;
            if (IsDbData)
            {
                dType = SqlCache.GetDataTypeList().FirstOrDefault(x => x.SqlType == dbType);
            }
            else
            {
                dType = SqlCache.GetDataTypeList().FirstOrDefault(x => x.C5Type == dataType);
            }

            if (dType != null)
            {
                if (type == 1)
                    result = dType.CSharpType;
                else
                    result = dType.SqlType;

                if (type == 1 && canNull && NotCanNull.FirstOrDefault(x => x.Equals(result, StringComparison.CurrentCultureIgnoreCase)) == null)
                {
                    result = string.Format("{0}?", result);
                }
            }
            else
            {
                throw new Exception("未能找到字段类型信息");
            }

            return result;
        }

        /// <summary>
        /// 获取特性
        /// </summary>
        /// <param name="isIdentity"></param>
        /// <param name="isKey"></param>
        /// <returns></returns>
        private string GetAttributes(bool isIdentity, bool isKey, string dataType, int maxLength, int scale, int precision)
        {
            StringBuilder resultAttributes = new StringBuilder();

            //key
            if (isKey)
                resultAttributes.Append("PrimaryKey = true, ");

            //自增
            if (isIdentity)
                resultAttributes.Append("AutoIncrement = true, ");

            //时间戳
            if (dataType == "timestamp")
                resultAttributes.Append("IsTimeStamp = true, ");

            //数据类型
            if (!string.IsNullOrWhiteSpace(dataType))
                resultAttributes.AppendFormat("DbType = \"{0}\", ", dataType);

            //最大
            if (maxLength != 0 && (dataType == "varchar" || dataType == "nvarchar" || dataType == "text"))
                resultAttributes.AppendFormat("MaxLength = {0}, ", maxLength);

            //最小
            if (scale != 0)
                resultAttributes.AppendFormat("Scale = {0}, ", scale);

            //精度
            if (precision != 0)
                resultAttributes.AppendFormat("Precision = {0}, ", precision);

            return string.Format("[C5SqlModel({0})]", resultAttributes.ToString().Trim().Trim(','));
        }

        /// <summary>
        /// 对象特性
        /// </summary>
        /// <param name="listEntity"></param>
        /// <returns></returns>
        private string GetTableAttributes(bool IsDbData, List<SYS_ENTITIES_LINES> listEntity = null, List<DBTableColmnsInfo> listTColumn = null)
        {
            StringBuilder sb = new StringBuilder();
            if (IsDbData)
            {
                var resultList = listTColumn.Where(x => x.PrimaryKey).ToList();
                foreach (var item in resultList)
                {
                    sb.AppendFormat("{0}, ", item.FieldName.Trim());
                }

                if (string.IsNullOrWhiteSpace(sb.ToString()))
                    return "";
            }
            else
            {
                var resultList = listEntity.Where(x => x.IsKey == true).ToList();
                foreach (var item in resultList)
                {
                    sb.AppendFormat("{0}, ", item.FIELD_CODE.Trim());
                }

                if (string.IsNullOrWhiteSpace(sb.ToString()))
                    return "";
            }

            return string.Format("[C5ClassModel(PrimaryKeys = \"{0}\")]", sb.ToString().Trim().Trim(','));
        }

        private void cmbModul_SelectedIndexChanged(object sender, EventArgs e)
        {
            GetXmlInfo();
        }

        /// <summary>
        /// 文件夹名称排序（顺序）
        /// </summary>
        /// <param name="dirs">待排序文件夹数组</param>
        private void SortAsFolderName(ref FileInfo[] files)
        {
            Array.Sort(files, delegate (FileInfo x, FileInfo y) { return x.Name.CompareTo(y.Name); });
        }

        #region 分文件

        /// <summary>
        /// 判断是否要创建新的文件
        /// </summary>
        /// <param name="filePath"></param>
        private void HandleAndCreateFile(ref string filePath)
        {
            string newPath = null;
            int maxCount = 500;
            //文件行数超过额定行数则创建新文件
            var rowCount = File.ReadAllLines(filePath).Length;
            if (rowCount > maxCount)
            {
                string fName = filePath.Substring(filePath.LastIndexOf(@"\")).Replace(@"\", "");
                if (!string.IsNullOrWhiteSpace(fName))
                {
                    List<FileInfo> list = new List<FileInfo>();
                    var files = new DirectoryInfo(filePath.Replace(fName, "")).GetFiles("*.cs");
                    foreach (var item in files)
                    {
                        if (item.Name.Equals(fName))
                        {
                            list.Add(item);
                            continue;
                        }

                        if (item.Name.Contains(fName.Replace(".cs", "")) && item.Name.Contains("_"))
                            list.Add(item);
                    }

                    var fileInfos = list.ToArray();
                    SortAsFolderName(ref fileInfos);

                    if (fileInfos.Length > 0)
                    {
                        var fileInfo = fileInfos[fileInfos.Length - 1];
                        if (fileInfo != null)
                        {
                            if (File.ReadAllLines(fileInfo.FullName).Length <= maxCount)
                            {
                                filePath = fileInfo.FullName;
                                return;
                            }

                            string name = "";
                            if (fileInfo.Name.Contains("_"))
                            {
                                string[] strName = fileInfo.Name.Replace(fileInfo.Extension, "").Split('_');
                                name = string.Format("{0}_{1}", strName[0], Convert.ToInt32(strName[1]) + 1);
                            }
                            else
                            {
                                name = string.Format("{0}_1", fileInfo.Name.Replace(fileInfo.Extension, ""));
                            }

                            newPath = string.Format(@"{0}\{1}.cs", fileInfo.DirectoryName, name);
                        }
                    }
                }
            }

            //写入文件引用及命名空间
            if (!string.IsNullOrWhiteSpace(newPath))
            {
                string str = File.ReadAllText(filePath);
                string otherStr = str.Substring(str.IndexOf("public", StringComparison.CurrentCultureIgnoreCase));

                StringBuilder sbstr = new StringBuilder();
                sbstr.Append(str.Replace(otherStr, ""));
                sbstr.Append("}");

                WriteModel(newPath, sbstr.ToString());
                filePath = newPath;
            }
        }

        #endregion

        #region Xml操作

        /// <summary>
        /// 保存配置信息
        /// </summary>
        private void SaveXml()
        {
            try
            {
                XmlHelper xmlHelper = new XmlHelper();

                //判断文件是否存在不存在创建
                if (!File.Exists(xmlPath))
                {
                    xmlHelper.CreateXmlDocument(xmlPath, "SOLUTION", "gb2312");
                }

                //判断是否又CreateModelConfig节点没有创建并创建其字节点
                XmlNode xn = xmlHelper.GetXmlNodeByXpath(xmlPath, "SOLUTION//CreateModelConfig");
                if (xn == null)
                {
                    Hashtable hashtable = new Hashtable();
                    hashtable.Add("ModulFileInfo", "");

                    xmlHelper.InsertNode(xmlPath, "CreateModelConfig", false, "SOLUTION", null, hashtable);
                }

                //创建和更新子节点信息
                string strNode = string.Format("SOLUTION//{0}", this.cmbModul.SelectedValue);
                var node = xmlHelper.GetXmlNodeByXpath(xmlPath, strNode);
                if (node == null)
                {
                    Hashtable ht = new Hashtable();
                    ht.Add("FilePath", this.txtFilePath.Text);
                    ht.Add("BaseModel", this.txtBaseModel.Text);
                    ht.Add("NameSpace", this.txtNameSpace.Text);
                    xmlHelper.InsertNode(xmlPath, this.cmbModul.SelectedValue.ToString(), false, "SOLUTION//ModulFileInfo", null, ht);
                }
                else
                {
                    //删除原节点信息并插入新信息
                    string fatherPath = "SOLUTION//ModulFileInfo";
                    xmlHelper.DeleteChildNodeByFatherPath(xmlPath, fatherPath, strNode);
                    Hashtable ht = new Hashtable();
                    ht.Add("FilePath", this.txtFilePath.Text);
                    ht.Add("BaseModel", this.txtBaseModel.Text);
                    ht.Add("NameSpace", this.txtNameSpace.Text);
                    xmlHelper.InsertNode(xmlPath, this.cmbModul.SelectedValue.ToString(), false, "SOLUTION//ModulFileInfo", null, ht);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 获取Xml配置信息
        /// </summary>
        private void GetXmlInfo()
        {
            if (this.cmbModul.SelectedIndex != -1)
            {
                XElement xele = XElement.Load(xmlPath);
                var reultNode = (from ele in xele.Descendants(this.cmbModul.SelectedValue.ToString())
                                 select ele).FirstOrDefault();

                if (reultNode != null)
                {
                    var filePath = reultNode.Element("FilePath");
                    if (filePath != null)
                        this.txtFilePath.Text = filePath.Value;

                    var baseModel = reultNode.Element("BaseModel");
                    if (baseModel != null)
                        this.txtBaseModel.Text = baseModel.Value;

                    var nameSpace = reultNode.Element("NameSpace");
                    if (nameSpace != null)
                        this.txtNameSpace.Text = nameSpace.Value;
                }
                else
                {
                    this.txtFilePath.Text = null;
                    this.txtBaseModel.Text = null;
                    this.txtNameSpace.Text = null;
                }
            }
        }

        #endregion

        #region 表说明

        /// <summary>
        /// EEP配置表说明
        /// </summary>
        private class TableColumnDescriptionByHG_C5Model
        {
            /// <summary>
            /// 表名
            /// </summary>
            public string ENTITY_CODE { get; set; }

            /// <summary>
            /// 字段
            /// </summary>
            public string FIELD_CODE { get; set; }

            /// <summary>
            /// 默认名称
            /// </summary>
            public string DefaultCaption { get; set; }
        }

        #endregion

    }
}
